package fun.codedesign.yinxue.text;

import fun.codedesign.yinxue.json.panel.JsonPanel;
import fun.codedesign.yinxue.text.domain.EditConfig;
import fun.codedesign.yinxue.text.panel.ConfirmPanel;
import fun.codedesign.yinxue.text.panel.ConsolePanel;
import fun.codedesign.yinxue.text.panel.EditPanel;
import fun.codedesign.yinxue.text.panel.HtmlPanel;
import fun.codedesign.yinxue.text.service.MarkdownService;
import fun.codedesign.yinxue.text.service.RunService;
import fun.codedesign.yinxue.text.service.impl.CodeRunService;
import fun.codedesign.yinxue.text.service.impl.CommonMarkdownService;
import fun.codedesign.yinxue.text.util.DirUtil;
import org.yinxue.swing.core.action.DirChooserActionListener;
import org.yinxue.swing.core.action.FileChooserActionListener;
import org.yinxue.swing.core.domain.FileObject;
import org.yinxue.swing.core.frame.YxFrame;
import org.yinxue.swing.core.panel.YxTree;
import org.yinxue.swing.core.standard.YxButton;
import org.yinxue.swing.core.standard.YxPanel;
import org.yinxue.swing.core.util.*;
import org.yinxue.swing.sql.main.SQLPanel2;
import org.yinxue.swing.unit.client.CheckCodeClient;
import org.yinxue.swing.unit.client.CodeClient;
import org.yinxue.swing.unit.client.CodeReport;
import org.yinxue.swing.unit.main.UnitPanel2;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.util.List;

public class TextPanel extends YxPanel {

    public CodeClient codeClient = new CheckCodeClient();
    public DirChooserActionListener dirChooserActionListener;
    public FileChooserActionListener fileChooserActionListener;

    public YxTree leftTree;

    public EditPanel rightTextArea;

    public ConsolePanel consoleTextArea;

    public YxPanel rightButtonPanel;


    public JSplitPane splitPane;

    public JSplitPane splitPane2;

    public YxPanel runPanel;

    public JPopupMenu rightClickMenu;

    YxButton runButton;

    ConfirmPanel newDirPanel;
    ConfirmPanel newFilePanel;

    ConfirmPanel renamePanel;

    EditConfig editConfig;


    @Override
    public void init() {
        editConfig = new EditConfig();
        dirChooserActionListener = new DirChooserActionListener();

        rightTextArea = new EditPanel();
        consoleTextArea = new ConsolePanel();

        rightButtonPanel = createYxPanel();

        runPanel = createYxPanel();

        rightClickMenu = new JPopupMenu();
        JMenuItem renamItem = new JMenuItem("重命名");
        JMenuItem deleteItem = new JMenuItem("删除");
        JMenuItem newFile = new JMenuItem("新建文件");
        JMenuItem newDir = new JMenuItem("新建文件夹");
        rightClickMenu.add(renamItem);
        rightClickMenu.add(deleteItem);
        rightClickMenu.add(newFile);
        rightClickMenu.add(newDir);

        renamePanel = new ConfirmPanel();
        renamePanel.confirmButton.addYxActionListener(getRenameAction());

        newFilePanel = new ConfirmPanel();
        newFilePanel.confirmButton.addYxActionListener(getNewFileAction());

        newDirPanel = new ConfirmPanel();
        newDirPanel.confirmButton.addYxActionListener(getNewDirAction());


        renamItem.addActionListener(e -> {
            // 重命名就将某文件夹修改名称, 读取文当前件/文件夹名称
            renamePanel.inputname.setText(editConfig.lastSelectedDir().file.getName());
            renamePanel.doRun();
        });
        deleteItem.addActionListener(getDeleteFileAction());
        newFile.addActionListener(e -> newFilePanel.doRun());
        newDir.addActionListener(e -> newDirPanel.doRun());

        fileChooserActionListener = new FileChooserActionListener().addYxValueChange(e ->
                rightTextArea.setText(fileChooserActionListener.text)
        );

        leftTree = createYxTree();
        // 最后选中的文件监听
        leftTree.addTreeSelectionListener(e -> {
            DefaultMutableTreeNode selectionNode = (DefaultMutableTreeNode) leftTree.getLastSelectedPathComponent();
            FileObject fileObject = null;
            if (selectionNode != null && selectionNode.getUserObject() instanceof FileObject) {
                fileObject = (FileObject) selectionNode.getUserObject();
            }
            if (selectionNode != null && selectionNode.isLeaf() && fileObject != null) {
                String text = fileObject.getText();
                rightTextArea.setText(text);
                // 缓存FileObject
//                lastSelectedFile = fileObject;
                editConfig.lastSelectedFile(fileObject);
            }
            if (selectionNode != null) {
                editConfig.lastSelectedDir((FileObject) selectionNode.getUserObject());
            }
        });

        // https://blog.csdn.net/paibigstar/article/details/81128116
        leftTree.jTree.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                // TODO Auto-generated method stub
                super.mouseClicked(e);
                int x = e.getX();
                int y = e.getY();

                if (e.getButton() == MouseEvent.BUTTON3) {
                    //menuItem.doClick(); //编程方式点击菜单项
                    TreePath pathForLocation = leftTree.jTree.getPathForLocation(x, y);//获取右键点击所在树节点路径
                    leftTree.jTree.setSelectionPath(pathForLocation);
                    rightClickMenu.show(leftTree.jTree, x, y);

                }
            }
        });
        splitPane2 = new JSplitPane(JSplitPane.VERTICAL_SPLIT, false, rightTextArea, consoleTextArea);
        splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, leftTree, splitPane2);
    }


    @Override
    public void position() {
        add(runPanel, refreshPosition(0, 0, 1, 1, 0, 0, V, GridBagConstraints.WEST));
        add(splitPane, refreshPosition(0, 1, 1, 1, 1, 1, BOTH));

        runButton = new YxButton();
        runButton.setSize(new Dimension(30, 30));
        runButton.setBorderPainted(false);
        runButton.setMargin(new Insets(0, 0, 0, 0));

        ImageIcon ico = SwingUtils.getICon(TextPanel.class, "/run.png");
        Image temp = ico.getImage().getScaledInstance(runButton.getWidth(), runButton.getHeight(), Image.SCALE_DEFAULT);
        ico = new ImageIcon(temp);

        runButton.setIcon(ico);

        runPanel.add(runButton, runPanel.refreshPosition(0, 0, 1, 1, 0, 0, V, new Insets(5, 5, 5, 5)));
    }

    MarkdownService markdownService = new CommonMarkdownService();

    @Override
    public void action() {
        dirChooserActionListener.addYxValueChange(e -> {
            refreshTree();
            EnvUtil.setProperty(TEXT_PROJECT, dirChooserActionListener.filePath);
            refreshDirs();
        });

        rightTextArea.addYxKeyListener(new KeyListener() {
            @Override
            public void keyTyped(KeyEvent e) {
            }

            @Override
            public void keyPressed(KeyEvent e) {
                System.out.println("keyPressed" + e.toString());
                // CTRL+S  : https://blog.csdn.net/withiter/article/details/17247617
                if (e.getModifiers() == 2 && e.getKeyCode() == 83)
                    if (editConfig.lastSelectedFile() != null) {
                        // 将编辑好的text 写入到 File文件中
                        editConfig.lastSelectedFile().write(rightTextArea.getText());
                    }
            }

            @Override
            public void keyReleased(KeyEvent e) {
            }
        });


        runButton.addYxActionListener(e -> {
            // 1. 对md文档进行预览  2. 对java文件进行编译，需要解决依赖问题
            if (editConfig.lastSelectedFile().file.getName().endsWith(".md")) {
                HtmlPanel htmlPanel = new HtmlPanel();
                String markdown = rightTextArea.getText();
                htmlPanel.setHtml(markdownService.html(markdown));
                htmlPanel.doRun();
            } else if (editConfig.lastSelectedFile().isJvmLang()) {
                // 1. 进入根目录  2.gradle build -x test 全量编译  3. java -classpath buildclass fun.codedesign.XXX
                String command = "cd /d " + getProjectText() + " & gradle build -x test";
                LogUtil.info(TextPanel.class, command);
                RuntimeUtil.execCallback(command, getConsoleCallback());
                String command2 = "cd /d " + getProjectText() + " & java -classpath " + getProjectText() + File.separator + editConfig.lastSelectedFile().findModule(getProjectText()) + File.separator + (editConfig.lastSelectedFile().isGroovy() ? "build\\classes\\groovy\\main " : "build\\classes\\java\\main ") + editConfig.lastSelectedFile().findPackage() + "." + editConfig.lastSelectedFile().file.getName().replace(".java", "").replace(".groovy", "");
                LogUtil.info(TextPanel.class, command2);
                RuntimeUtil.execCallback(command2, getConsoleCallback());
            }
        });

        // 初始化时根据input_text构建jtree
        refreshTree();

        // 初始化列表
        refreshDirs();
    }

    public Callback getConsoleCallback() {
        return target -> {
            // 控制台打印出来
            LogUtil.info(TextPanel.class, target);
            consoleTextArea.appendAndRefresh((String) target);
        };
    }

    public ActionListener getBatchCodeCheckAction() {
        return e -> {
            List<CodeReport> reports = codeClient.batchCheckCode(getEditText());
            System.out.println(reports);
        };
    }

    public ActionListener getCodeCheckAction() {
        return e -> {
            CodeReport report = codeClient.checkCode(getEditText());
            System.out.println(report);
        };
    }

    ActionListener getDeleteFileAction() {
        return e -> {
            List<Object> fileObjects = leftTree.getSelectObjects();
            fileObjects.stream().forEach(object -> ((FileObject) object).delete());
            // 刷新树
            refreshTree();
            File parent = editConfig.lastSelectedDir().file.getParentFile();
            FileObject object = new FileObject(parent.getName(), parent);
            leftTree.expand(object);
        };
    }

    String getProjectText() {
        return editConfig.projectDir().file.getAbsolutePath();
    }

    String getEditText() {
        return rightTextArea.getText();
    }

    ActionListener getGitPullAction() {
        return e -> {
            String command = "cd /d " + getProjectText() + "& git pull";
            RuntimeUtil.execAysncCallback(command, getConsoleCallback());
        };
    }

    ActionListener getGitPushAction() {
        return e -> {
            String command = "cd /d " + getProjectText() + "& git status & git add . & git commit -m \"yinxue-text commit\" & git push";
            RuntimeUtil.execAysncCallback(command, getConsoleCallback());
        };
    }

    ActionListener getSaveTextAction() {
        return e -> {
            if (editConfig.lastSelectedFile() != null) {
                // 将编辑好的text 写入到 File文件中
                editConfig.lastSelectedFile().write(rightTextArea.getText());
            }
        };
    }

    ActionListener getNewDirAction() {
        return e4 -> {
            newDirPanel.jFrame.setVisible(false);
            if (editConfig.lastSelectedDir() != null && editConfig.lastSelectedDir().isDir()) {
                // 将编辑好的text 写入到 File文件中
                String dirName = newDirPanel.inputname.getText();
                editConfig.lastSelectedDir().newDir(dirName);
            }
            newDirPanel.jFrame.dispose();
            refreshTree();
            leftTree.expand(editConfig.lastSelectedDir());
        };
    }

    ActionListener getRenameAction() {
        return e4 -> {
            renamePanel.jFrame.setVisible(false);
            editConfig.lastSelectedDir().file.renameTo(new File(editConfig.lastSelectedDir().file.getParent(), renamePanel.inputname.getText()));
            renamePanel.jFrame.dispose();
            refreshTree();
            // 展开重命名文件/文件夹的上一个文件/文件夹避免找不到
            leftTree.expand(new FileObject(editConfig.lastSelectedDir().file.getParentFile().getName(), editConfig.lastSelectedDir().file.getParentFile()));
        };
    }


    ActionListener getNewFileAction() {
        return e3 -> {
            newFilePanel.jFrame.setVisible(false);

            if (editConfig.lastSelectedDir() != null && editConfig.lastSelectedDir().isDir()) {
                // 将编辑好的text 写入到 File文件中
                String fileName = newFilePanel.inputname.getText();
                editConfig.lastSelectedDir().newFile(fileName);
            }
            newFilePanel.jFrame.dispose();
            refreshTree();
            leftTree.expand(editConfig.lastSelectedDir());
        };


    }

    public FileChooserActionListener getFileChooserAction() {
        FileChooserActionListener listener = new FileChooserActionListener();
        listener.addYxValueChange(e -> {
            rightTextArea.setText(listener.text);
            File file = new File(listener.filePath);
            editConfig.lastSelectedFile(new FileObject(file.getName(), file));
        });
        return listener;
    }

    RunService runService = new CodeRunService();

    ActionListener getRunAction() {
        return e -> {
            runService.runCode(null);
        };
    }

    static final String TEXT_PROJECT = "text_project";

    void refreshTree() {
        leftTree.refreshTree(getProjectText());
    }

    static boolean refreshDirsFlag = false;

    void refreshDirs() {
        refreshDirsFlag = true;

        String[] dirArray = DirUtil.getDirs();
        if (dirArray.length != 0) {
//            downSelect.removeAllItems();
//            for (String s : dirArray) {
//                File file = new File(s);
//                FileObject item = new FileObject(file.getName(), file);
//                if (s.equals(EnvUtil.getProperty(TEXT_PROJECT))) {
//                    downSelect.addItem(item);
//                    downSelect.setSelectedItem(item);
//                } else {
//                    downSelect.addItem(item);
//                }
//            }
        }
        refreshDirsFlag = false;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            SwingUtils.initDefaultUI();
            try {
                TextPanel jPanel = TextPanel.class.newInstance();

                YxFrame yxFrame = new YxFrame("编辑器")
                        .size(1600, 900)
                        .menu("文件", "打开文件", jPanel.getFileChooserAction()) // TODO 等待替换为选取文件的
                        .menu("文件", "打开文件夹", jPanel.dirChooserActionListener)
                        .menu("文件", "保存", jPanel.getSaveTextAction())
                        .menu("文件", "新建文件", jPanel.getNewFileAction())
                        .menu("文件", "新建文件夹", jPanel.getNewDirAction())
                        // TODO https://www.cnpython.com/java/630039
                        .popMenu("文件", "最近文件夹", DirUtil.getDirs(), new ActionListener[]{}, new ActionListener() {
                            @Override
                            public void actionPerformed(ActionEvent e) {
                                System.out.println(e.getActionCommand());
                                jPanel.leftTree.refreshTree(e.getActionCommand());
                                // TODO 将文件的最后一个
                                File file = new File(e.getActionCommand());
                                jPanel.editConfig.projectDir(new FileObject(file.getName(), file));
                            }
                        })
                        .menu("编辑", "删除", jPanel.getDeleteFileAction())
                        .menu("编辑", "展开", e -> jPanel.leftTree.expand(jPanel.editConfig.lastSelectedDir()))
                        .menu("编辑", "当前代码检查", jPanel.getCodeCheckAction())
                        .menu("编辑", "代码目录检查", jPanel.getBatchCodeCheckAction())
                        .menu("仓库", "git拉取", jPanel.getGitPullAction())
                        .menu("仓库", "git推送", jPanel.getGitPushAction())
                        .menu("工具", "json工具", e -> JsonPanel.run())
                        .menu("工具", "sql工具", e -> SQLPanel2.run())
                        .menu("工具", "unit工具", e -> UnitPanel2.run())
                        .menu("帮助", "检查更新", e -> JOptionPane.showMessageDialog(null, "建设中"))
                        .menu("帮助", "问题反馈", e -> JOptionPane.showMessageDialog(null, "建设中"))
                        .menu("帮助", "配置编辑", e -> {
                            jPanel.editConfig.lastSelectedFile(new FileObject("yinxue-setting", EnvUtil.readFile()));
                            jPanel.rightTextArea.setText(EnvUtil.readText());
                        })
                        .menu("帮助", "关于", e -> JOptionPane.showMessageDialog(null, "by zengjian"))
                        .panel(jPanel);
                yxFrame.visible(true);
                // 分割线失效问题 https://blog.51cto.com/u_15762357/5612289
                jPanel.splitPane2.setDividerLocation(0.8);
                jPanel.splitPane.setDividerLocation(0.2);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
    }
}
